home *** CD-ROM | disk | FTP | other *** search
- /*
- Terminal 2.0
- "MacBinary.c"
- */
-
- #ifdef THINK_C
- #include "MacHeaders"
- #endif
- #ifdef applec
- #pragma load ":(Objects):MacHeadersMPW"
- #pragma segment Main2
- #endif
-
- #include "MacBinary.h"
- #include "CRC.h"
- #include "Utilities.h"
-
- typedef struct {
- Byte oldVersion; /* 000: Must be zero for compatibility */
- Byte name[64]; /* 001: Pascal string */
- Byte info1[16]; /* 065: Original Finder info: */
- /* File type (long) */
- /* File creator (long) */
- /* Flags (word, low byte must be zero) */
- /* File's location (Point) */
- /* File's window (short) */
- Byte protected; /* 081: Low order bit */
- Byte zero1; /* 082: Must be zero for compatibility */
- Byte dLength[4]; /* 083: Data fork length (in bytes) */
- Byte rLength[4]; /* 087: Resource fork length (in bytes) */
- Byte creation[4]; /* 091: Creation date */
- Byte modification[4]; /* 095: Modification date */
- Byte getInfoLength[2]; /* 099: Get info length */
- Byte info2; /* 101: Finder flags, low byte */
- Byte zero2[14]; /* 102: Not used */
- Byte filesLength[4]; /* 116: Length of total unpacked files */
- Byte sHeaderLength[2]; /* 120: Length of secondary header */
- Byte newVersion; /* 122: Uploading program version number */
- Byte minimumVersion; /* 123: Minimum version number needed */
- Byte crc[2]; /* 124: CRC of previous 124 bytes */
- Byte zero3[2]; /* 126: Not used */
- } HEADER;
-
- #define DESKTOP 0x0001 /* ---- ---- ---- ---1 */
- #define COLOR 0x000E /* ---- ---- ---- 111- */
- #define INITED 0x0100 /* ---- ---1 ---- ---- */
- #define CHANGED 0x0200 /* ---- --1- ---- ---- */
- #define BUSY 0x0400 /* ---- -1-- ---- ---- */
- #define BOZO 0x0800 /* ---- 1--- ---- ---- */
- #define SYSTEM 0x1000 /* ---1 ---- ---- ---- */
- #define BUNDLE 0x2000 /* --1- ---- ---- ---- */
- #define INVISIBLE 0x4000 /* -1-- ---- ---- ---- */
- #define LOCKED 0x8000 /* 1--- ---- ---- ---- */
-
- #define NOMODIFY (DESKTOP | INITED | CHANGED | BUSY)
-
- typedef struct {
- Byte name[64]; /* File name */
- short volume; /* Volume reference number */
- long directory; /* Directory ID */
- short ref; /* File reference number */
- long data; /* Size of data fork */
- long resource; /* Size of resource fork */
- long mark; /* Current read/write mark */
- HEADER header; /* MacBinary header */
- } MBFCB;
-
- static MBFCB **File = 0; /* Current file control block handle */
-
- /* ----- Minimum ------------------------------------------------------- */
-
- static long Minimum(register long a, register long b)
- {
- return (a < b) ? a : b;
- }
-
- /* ----- Set up MacBinary header --------------------------------------- */
-
- static short InitMacBinary(
- short volume,
- long directory,
- Byte *name,
- HEADER *header,
- long *data,
- long *resource)
- {
- register short err;
- register Byte *p;
- unsigned short crc;
- HFileParam param;
-
- memset(¶m, 0, sizeof(param));
- param.ioNamePtr = (StringPtr)name;
- param.ioVRefNum = volume;
- param.ioDirID = directory;
- if (err = PBHGetFInfo((HParmBlkPtr)¶m, FALSE))
- return err;
-
- p = (Byte *)header + sizeof(HEADER);
- do
- *(--p) = 0;
- while (p > (Byte *)header);
-
- memcpy(header->name, name, name[0] + 1);
- header->info2 = param.ioFlFndrInfo.fdFlags & 0x00FF;
- param.ioFlFndrInfo.fdFlags &= 0xFF00;
- *(long *)¶m.ioFlFndrInfo.fdLocation = 0;
- param.ioFlFndrInfo.fdFldr = 0;
- memcpy((void *)header->info1, (void *)¶m.ioFlFndrInfo,
- sizeof(header->info1));
- header->protected = (Byte)(param.ioFlAttrib) & 0x01;
- memcpy((void *)header->dLength, (void *)¶m.ioFlLgLen, 4);
- memcpy((void *)header->rLength, (void *)¶m.ioFlRLgLen, 4);
- memcpy((void *)header->creation, (void *)¶m.ioFlCrDat, 4);
- memcpy((void *)header->modification, (void *)¶m.ioFlMdDat, 4);
- header->newVersion = 129;
- header->minimumVersion = 129;
- crc = CalcCRC((Byte *)header, 124, 0);
- memcpy((void *)header->crc, (void *)&crc, 2);
-
- *data = param.ioFlLgLen;
- *resource = param.ioFlRLgLen;
- return 0;
- }
-
- /* ----- Verify MacBinary header --------------------------------------- */
-
- short BinCheckHeader(
- register Byte *p,
- Byte *name, /* File name */
- long *data, /* Data fork length */
- long *resource) /* Resource fork length */
- {
- register short i, j, version;
- register HEADER *header;
- unsigned short crc;
-
- *name = 0;
- *data = *resource = 0;
- header = (HEADER *)p;
- if (p[0] || p[74] || p[82] || p[83] || p[87] ||
- (i = header->name[0]) > 63)
- return 0;
- memcpy((void *)&crc, (void *)header->crc, 2);
- if (crc == CalcCRC((Byte *)header, 124, 0) &&
- header->minimumVersion <= 129)
- version = 2;
- else {
- for (j = 101; j < 125; j++)
- if (p[j])
- return 0;
- version = 1;
- }
- memcpy((void *)name, (void *)header->name, i + 1);
- memcpy((void *)data, (void *)header->dLength, 4);
- memcpy((void *)resource, (void *)header->rLength, 4);
- return version;
- }
-
- /* ----- Set up file info from MacBinary header ------------------------ */
-
- static short SetupMacBinary(
- HEADER *header,
- short volume,
- long directory,
- Byte *name)
- {
- register short err;
- HFileParam param;
- FInfo info;
-
- memset(¶m, 0, sizeof(param));
- param.ioNamePtr = (StringPtr)name;
- param.ioVRefNum = volume;
- param.ioDirID = directory;
- if (err = PBHGetFInfo((HParmBlkPtr)¶m, FALSE))
- return err;
-
- memcpy((void *)&info, (void *)header->info1, sizeof(info));
- info.fdFlags &= 0xFF00; /* High byte */
- info.fdFlags |= header->info2; /* Low byte */
- info.fdFlags &= ~NOMODIFY;
- param.ioFlFndrInfo.fdType = info.fdType;
- param.ioFlFndrInfo.fdCreator = info.fdCreator;
- param.ioFlFndrInfo.fdFlags &= NOMODIFY;
- param.ioFlFndrInfo.fdFlags |= info.fdFlags;
- memcpy((void *)¶m.ioFlCrDat, (void *)header->creation, 4);
- memcpy((void *)¶m.ioFlMdDat, (void *)header->modification, 4);
- param.ioNamePtr = (StringPtr)name;
- param.ioVRefNum = volume;
- param.ioDirID = directory;
- return PBHSetFInfo((HParmBlkPtr)¶m, FALSE);
- }
-
- /* ----- Open disk file for reading ------------------------------------ */
-
- short BinOpenRead(
- register short volume,
- register long directory,
- register Byte *name)
- {
- register MBFCB **f;
- register MBFCB *p;
- register short err;
-
- if (File)
- return 1; /* Is already open! */
- if (!(f = (MBFCB **)NewHandle(sizeof(MBFCB))))
- return 2; /* Memory problem! */
-
- HLock((Handle)f);
- p = *f;
- if (!(err = InitMacBinary(volume, directory, name,
- &p->header, &p->data, &p->resource))) {
- memcpy((void *)p->name, (void *)name, name[0] + 1);
- p->volume = volume;
- p->directory = directory;
- p->mark = 0;
- }
- HUnlock((Handle)f);
- if (err)
- DisposHandle((Handle)f);
- else
- File = f; /* Now is open */
- return err;
- }
-
- /* ----- Read from disk file ------------------------------------------- */
-
- short BinRead(
- long *count,
- Byte *buffer)
- {
- register MBFCB **f;
- register MBFCB *p;
- register short err;
- register long n;
- long b, c, d, e;
- long i;
-
- if (!(f = File))
- return 1; /* Is not open! */
- HLock((Handle)f);
- p = *f;
-
- b = sizeof(HEADER) + p->data;
- c = b + Filler(BinHeaderLength, p->data);
- d = c + p->resource;
- e = d + Filler(BinHeaderLength, p->resource);
-
- /* Open data fork of file if necessary */
-
- if (p->mark == sizeof(HEADER) &&
- (err = OpenFile(p->volume,p->directory,p->name,&p->ref)))
- goto done;
-
- /* Close data fork of file if necessary */
-
- if (p->mark == b) {
- FSClose(p->ref);
- p->ref = 0;
- }
-
- /* Open resource fork of file if necessary */
-
- if (p->mark == c &&
- (err = OpenResource(p->volume,p->directory,p->name,&p->ref)))
- goto done;
-
- /* Close resource fork of file if necessary */
-
- if (p->mark == d) {
- FSClose(p->ref);
- p->ref = 0;
- }
-
- /* Copy from header */
-
- if (p->mark < sizeof(HEADER)) {
- n = Minimum(*count, sizeof(HEADER) - p->mark);
- memcpy((void *)buffer, (Byte *)&p->header + p->mark, n);
- goto allright;
- }
-
- /* Read data fork */
-
- if (p->mark < b) {
- i = Minimum(*count, b - p->mark);
- err = FSRead(p->ref, &i, buffer);
- n = i;
- goto done;
- }
-
- /* Clear buffer (fill up to entire multiple of 128 bytes) */
-
- if (p->mark < c) {
- n = Minimum(*count, c - p->mark);
- memset(buffer, 0, n);
- goto allright;
- }
-
- /* Read resource fork */
-
- if (p->mark < d) {
- i = Minimum(*count, d - p->mark);
- err = FSRead(p->ref, &i, buffer);
- n = i;
- goto done;
- }
-
- /* Clear buffer (fill up to entire multiple of 128 bytes) */
-
- if (p->mark < e) {
- n = Minimum(*count, e - p->mark);
- memset(buffer, 0, n);
- goto allright;
- }
-
- /* End of file reached */
-
- err = eofErr;
- n = 0;
- goto done;
-
- allright:
- err = 0; /* No error */
- done:
- if (!err) {
- p->mark += n;
- if (c = *count - n)
- err = BinRead(&c, buffer + n);
- *count = n + c;
- } else {
- if (err == eofErr) {
- p->mark += n;
- *count = n;
- }
- }
-
- HUnlock((Handle)f);
- return err;
- }
-
- /* ----- Close disk file after reading --------------------------------- */
-
- short BinCloseRead(void)
- {
- register short ref;
-
- if (!File)
- return 1; /* Is not open! */
- if (ref = (**File).ref)
- FSClose(ref); /* Data or resource fork */
- DisposHandle((Handle)File);
- File = 0; /* Now file is closed */
- return 0;
- }
-
- /* ----- Open disk file for writing ------------------------------------ */
-
- short BinOpenWrite(
- register short volume,
- register long directory,
- register Byte *name,
- register Byte *header)
- {
- register MBFCB **f;
- register MBFCB *p;
- Byte name2[64];
-
- if (File)
- return 1; /* Is already open! */
-
- if (!(f = (MBFCB **)NewHandle(sizeof(MBFCB))))
- return 2; /* Memory problem! */
-
- HLock((Handle)f);
- p = *f;
-
- BinCheckHeader(header, name2, &p->data, &p->resource);
- memcpy((void *)&p->header, (void *)header, sizeof(HEADER));
- memcpy((void *)p->name, (void *)name, name[0] + 1);
- p->volume = volume;
- p->directory = directory;
- p->mark = sizeof(HEADER);
-
- HUnlock((Handle)f);
- File = f; /* Now is open */
- return 0;
- }
-
- /* ----- Write to disk file -------------------------------------------- */
-
- short BinWrite(
- long *count,
- Byte *buffer)
- {
- register MBFCB **f;
- register MBFCB *p;
- register short err;
- register long n;
- long b, c, d, e;
- long i;
-
- if (!(f = File))
- return 1; /* Is not open! */
- HLock((Handle)f);
- p = *f;
-
- b = sizeof(HEADER) + p->data;
- c = b + Filler(BinHeaderLength, p->data);
- d = c + p->resource;
- e = d + Filler(BinHeaderLength, p->resource);
-
- /* Open data fork of file if necessary */
-
- if (p->mark == sizeof(HEADER) &&
- (err = OpenFile(p->volume,p->directory,p->name,&p->ref)))
- goto done;
-
- /* Close data fork of file if necessary */
-
- if (p->mark == b) {
- FSClose(p->ref);
- p->ref = 0;
- }
-
- /* Open resource fork of file if necessary */
-
- if (p->mark == c &&
- (err = OpenResource(p->volume,p->directory,p->name,&p->ref)))
- goto done;
-
- /* Close resource fork of file if necessary */
-
- if (p->mark == d) {
- FSClose(p->ref);
- p->ref = 0;
- }
-
- /* Ignore header */
-
- if (p->mark < sizeof(HEADER)) {
- n = Minimum(*count, sizeof(HEADER) - p->mark);
- goto allright;
- }
-
- /* Write data fork */
-
- if (p->mark < b) {
- i = Minimum(*count, b - p->mark);
- err = FSWrite(p->ref, &i, buffer);
- n = i;
- goto done;
- }
-
- /* Ignore buffer (filled up to entire multiple of 128 bytes) */
-
- if (p->mark < c) {
- n = Minimum(*count, c - p->mark);
- goto allright;
- }
-
- /* Write resource fork */
-
- if (p->mark < d) {
- i = Minimum(*count, d - p->mark);
- err = FSWrite(p->ref, &i, buffer);
- n = i;
- goto done;
- }
-
- /* Ignore buffer (filled up to entire multiple of 128 bytes) */
-
- if (p->mark < e) {
- n = Minimum(*count, e - p->mark);
- goto allright;
- }
-
- /* End of file reached (can happen if using XModem 1K) */
-
- err = eofErr;
- n = 0;
- goto done;
-
- allright:
- err = 0; /* No error */
- done:
- if (!err) {
- p->mark += n;
- if (c = *count - n)
- err = BinWrite(&c, buffer + n);
- *count = n + c;
- } else {
- if (err == eofErr) {
- p->mark += n;
- *count = n;
- err = noErr;
- }
- }
-
- HUnlock((Handle)f);
- return err;
- }
-
- /* ----- Close disk file after writing --------------------------------- */
-
- short BinCloseWrite(void)
- {
- register short err;
- register MBFCB **f;
- register MBFCB *p;
-
- if (!(f = File))
- return 1; /* Is not open! */
- HLock((Handle)f);
- p = *f;
- err = SetupMacBinary((HEADER *)&p->header, p->volume, p->directory,
- p->name);
- if (p->ref)
- FSClose(p->ref); /* Data or resource fork */
- FlushVol(0, p->volume);
- HUnlock((Handle)f);
- DisposHandle((Handle)f);
- File = 0; /* Now file is closed */
- return err;
- }
-
- /* ----- Get length of complete MacBinary file ------------------------- */
-
- short BinGetEOF(register long *eof)
- {
- register MBFCB **f;
- register MBFCB *p;
-
- *eof = 0;
- if (!(f = File))
- return 1; /* Is not open! */
- p = *f;
- *eof = BinHeaderLength +
- p->data + Filler(BinHeaderLength, p->data) +
- p->resource + Filler(BinHeaderLength, p->resource);
- return 0;
- }
-